package com.yami.shop.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.cashregisterapp.AppRefundGoods;
import com.yami.shop.bean.cashregisterapp.AppTransactionRefund;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.pay.Orderparm;
import com.yami.shop.dao.*;
import com.yami.shop.service.AppRefundGoodsService;
import com.yami.shop.service.OrderItemService;
import com.yami.shop.service.OrderService;
import lombok.AllArgsConstructor;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import com.yami.shop.bean.pay.RefundGoodsDto;
import org.springframework.transaction.interceptor.TransactionAspectSupport;


@Service
@AllArgsConstructor
public class AppRefundGoodsServiceImpl extends
        ServiceImpl<AppRefundGoodsMapper,AppRefundGoods> implements AppRefundGoodsService{

    private final AppRefundGoodsMapper appRefundGoodsMapper;

    private final OrderService orderService;

    private final OrderItemService orderItemService;

    private final AppTransactionRefundMapper appTransactionRefundMapper;

    private final UserMapper userMapper;

    private static String authorization;

    private final SkuMapper skuMapper;

    private final ProductMapper productMapper;

    @Override
    @Transactional
    public RefundGoodsDto refund(Orderparm orderParams, Long appCashRegisterSystemUserId, String merchantCode, String terminalCode,
                                 String refund, Long shopId,String appId,String appKey,boolean isVip) throws  Exception{
        List<Product> productList = orderParams.getProductList();
        RefundGoodsDto refundGoodsDto = new RefundGoodsDto();
        //退还商品总数量
        int productCount = 0;
        for (Product product : productList) {
            productCount = product.getCount() + productCount;
        }
        refundGoodsDto.setRefundAccount(productCount);
        Order order = orderService.getOrderByOrderNumber(orderParams.getOrderNumber());
        //订单中，购买商品总数量
        int buyProductCount = order.getProductNums();
        //需要退还的金额
        BigDecimal refundAccountTotal = new BigDecimal("0.00");
        List<AppRefundGoods> appRefundGoodsList = new ArrayList<>();
        //退货，修改订单状态
        for (Product product : productList) {
            //查询子订单项
            OrderItem orderItem = orderItemService.getOrderItemByParam(orderParams.getOrderNumber(), product.getProdId().toString());
            Integer prodCount1 = orderItem.getProdCount();
            Product product1=productMapper.getProdcut(orderItem.getProdId());
            product1.setTotalStocks(product1.getTotalStocks()+prodCount1);
            productMapper.updateById(product1);
            Sku sku = skuMapper.selectById(orderItem.getSkuId());
            sku.setStocks(sku.getStocks()+prodCount1);
            skuMapper.updateById(sku);
            if (product.getCount() == orderItem.getProdCount()) {//删除子订单 全部退货
                orderItemService.deleteOrderItemByParam(orderParams.getOrderNumber(), orderItem.getProdId().toString());
                AppRefundGoods appRefundGoods = new AppRefundGoods();
                appRefundGoods.setShopId(orderItem.getShopId());
                appRefundGoods.setOrderNumber(orderParams.getOrderNumber());
                appRefundGoods.setProdId(orderItem.getProdId());
                appRefundGoods.setSkuId(orderItem.getSkuId());
                appRefundGoods.setProdCount(orderItem.getProdCount());
                appRefundGoods.setProdName(orderItem.getProdName());
                appRefundGoods.setSkuName(orderItem.getSkuName());
                appRefundGoods.setPic(orderItem.getPic());
                appRefundGoods.setPrice(orderItem.getPrice());
                appRefundGoods.setUserId(orderItem.getUserId());
                appRefundGoods.setProductTotalAmount(orderItem.getProductTotalAmount());
                appRefundGoods.setRecTime(orderItem.getRecTime());
                appRefundGoods.setCommSts(orderItem.getCommSts());
                appRefundGoods.setBasketDate(orderItem.getBasketDate());
                appRefundGoods.setCashRegisterSystemUserId(appCashRegisterSystemUserId);
                appRefundGoodsMapper.insert(appRefundGoods);
                appRefundGoodsList.add(appRefundGoods);
                refundAccountTotal = refundAccountTotal.add(new BigDecimal(orderItem.getProductTotalAmount()).setScale(2, BigDecimal.ROUND_UP ));
                buyProductCount = buyProductCount - product.getCount();
            } else {//部分退货
                AppRefundGoods appRefundGoods = new AppRefundGoods();
                appRefundGoods.setShopId(orderItem.getShopId());
                appRefundGoods.setOrderNumber(orderParams.getOrderNumber());
                appRefundGoods.setProdId(orderItem.getProdId());
                appRefundGoods.setSkuId(orderItem.getSkuId());
                appRefundGoods.setProdCount(orderItem.getProdCount());
                appRefundGoods.setProdName(orderItem.getProdName());
                appRefundGoods.setSkuName(orderItem.getSkuName());
                appRefundGoods.setPic(orderItem.getPic());
                appRefundGoods.setPrice(orderItem.getPrice());
                appRefundGoods.setUserId(orderItem.getUserId());
                appRefundGoods.setProductTotalAmount(orderItem.getProductTotalAmount());
                appRefundGoods.setRecTime(orderItem.getRecTime());
                appRefundGoods.setCommSts(orderItem.getCommSts());
                appRefundGoods.setBasketDate(orderItem.getBasketDate());
                appRefundGoods.setCashRegisterSystemUserId(appCashRegisterSystemUserId);
                appRefundGoodsMapper.insert(appRefundGoods);
                appRefundGoodsList.add(appRefundGoods);
                //修改子订单购买数量和价格
                int prodCount = orderItem.getProdCount() - product.getCount();
                Double productTotalAmount = orderItem.getPrice() * prodCount;
                orderItem.setProdCount(prodCount);
                orderItem.setProductTotalAmount(productTotalAmount);
                orderItemService.saveOrUpdate(orderItem);
                buyProductCount = buyProductCount - product.getCount();
                if(orderItem.getVipPrice()!=null) {
                    refundAccountTotal = refundAccountTotal.add(orderItem.getVipPrice().multiply(new BigDecimal(product.getCount()))).setScale(2, BigDecimal.ROUND_UP );
                }else{
                    refundAccountTotal = refundAccountTotal.add(new BigDecimal(product.getCount() * orderItem.getPrice()).setScale(2, BigDecimal.ROUND_UP ));
                }
            }
        }
        refundGoodsDto.setAccount(refundAccountTotal);//退款金额
        refundGoodsDto.setAppRefundGoodsList(appRefundGoodsList);//退款商品列表
        if (buyProductCount == 0) {
            //全部退货
            order.setRefundState(2);
            orderService.saveOrUpdate(order);
        } else {
            order.setProductNums(buyProductCount);//订单商品总数
            order.setActualTotal(order.getActualTotal() - refundAccountTotal.doubleValue());//实际总值
            orderService.saveOrUpdate(order);
        }
        //支付方式 0 现金支付 1 微信支付 2 银联支付 3 账户余额支付
        if (order.getPayType() == 0) {
            //现金支付，退还现金
            refundGoodsDto.setIsSuccess(true);
            refundGoodsDto.setRefundType(0);
        } else if (order.getPayType() == 2) {
            //订单退还到原来的账户
            String refundRequestId = "";
            String payCode = null;
            AppTransactionRefund appTransactionRefund = new AppTransactionRefund();
            appTransactionRefund.setMerchantOrderId(Long.valueOf(orderParams.getOrderNumber()));
            appTransactionRefund.setOriginalOrderId(orderParams.getOriginalOrderId());
            List<AppTransactionRefund> appTransactionRefundList = appTransactionRefundMapper.getList(appTransactionRefund);
            if (CollectionUtils.isNotEmpty(appTransactionRefundList)) {
                refundRequestId = appTransactionRefundList.get(0).getRefundRequestId();
                payCode = appTransactionRefundList.get(0).getPayCode();
            } else {
                refundRequestId = DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS") + RandomStringUtils.randomNumeric(4);
            }
            /* post参数,格式:JSON */
            JSONObject body = new JSONObject();
            body.put("merchantCode", merchantCode);   // 商户号
            body.put("terminalCode", terminalCode);   // 终端号
            body.put("merchantOrderId",orderParams.getOrderNumber());
            //body.put("originalOrderId", orderParams.getOrderNumber());    // 银商订单号,必须与原支付交易返回的订单号一致
            body.put("refundRequestId", refundRequestId); // 退款请求标识,标识一次退款请求,跟退款订单号一个效果
            //body.put("transactionAmount", refundAccountTotal.multiply(new BigDecimal(100)).setScale( 0, BigDecimal.ROUND_UP ));   // 退货金额,代表本次退货的金额,小于或等于原支付金额
            body.put("transactionAmount",1);
            String send = send(refund,body.toString(),appId,appKey);
            JSONObject json = new JSONObject(send);
            String errCode = json.getString("errCode");
            refundGoodsDto.setResult(send);//银联接口返回信息
            if (errCode.equals("00")) {//退款成功
                AppTransactionRefund appTransactionRefund1 = new AppTransactionRefund();
                appTransactionRefund1.setMerchantCode(merchantCode);
                appTransactionRefund1.setTerminalCode(terminalCode);
                appTransactionRefund1.setMerchantOrderId(Long.valueOf(orderParams.getOrderNumber()));
                appTransactionRefund1.setOriginalOrderId(orderParams.getOrderNumber());
                appTransactionRefund1.setRefundRequestId(refundRequestId);
                appTransactionRefund1.setCreateTime(new Date());
                appTransactionRefund1.setShopId(shopId);
                appTransactionRefund1.setUserId(shopId);
                appTransactionRefund1.setPayCode(payCode);
                appTransactionRefund1.setAmount(refundAccountTotal.multiply(new BigDecimal(100)).intValue());
                appTransactionRefundMapper.insert(appTransactionRefund1);
                refundGoodsDto.setIsSuccess(true);
                refundGoodsDto.setRefundType(1);
            } else {
                //退款失败
                refundGoodsDto.setIsSuccess(false);
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return refundGoodsDto;
            }
        } else if (order.getPayType() == 3) {
            //账户余额支付，退还到原来的账户
            User user = userMapper.selectById(order.getUserId());
            user.setAccount(user.getAccount() + refundAccountTotal.doubleValue());
            userMapper.updateById(user);
            refundGoodsDto.setRefundType(1);
        } else {
            refundGoodsDto.setIsSuccess(false);
        }
        return refundGoodsDto;
    }
    /**
     * 发送请求
     * */
    public String send(String url,String entity,String appId,String appKey) throws Exception{
        authorization = getOpenBodySig(appId,appKey,entity);
        System.out.println("authorization"+authorization);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Authorization", authorization);
        StringEntity se = new StringEntity(entity, "UTF-8");
        se.setContentType("application/json");
        System.out.println("se"+se);
        httpPost.setEntity(se);
        CloseableHttpResponse response = httpClient.execute(httpPost);
        HttpEntity entity1 = response.getEntity();
        String resStr = null;
        if (entity1 != null) {
            resStr = EntityUtils.toString(entity1, "UTF-8");
        }
        httpClient.close();
        response.close();
        return resStr;
    }
    /**
     * open-body-sig方式获取到Authorization 的值
     *
     * @param appId
     * @param appKey
     * @param body
     * @return
     * @throws Exception
     */
    public static String getOpenBodySig(String appId, String appKey, String body) throws Exception {
        String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());   // eg:20190227113148
        String nonce = UUID.randomUUID().toString().replace("-", ""); // eg:be46cd581c9f46ecbd71b9858311ea12
        byte[] data = body.getBytes("UTF-8");
        System.out.println("data:\n" + body);
        InputStream is = new ByteArrayInputStream(data);
        String bodyDigest = testSHA256(is); // eg:d60bc3aedeb853e2a11c0c096baaf19954dd9b752e48dea8e919e5fb29a42a8d
        System.out.println("bodyDigest:\n" + bodyDigest);
        String str1_C = appId + timestamp + nonce + bodyDigest; // eg:f0ec96ad2c3848b5b810e7aadf369e2f + 20190227113148 + be46cd581c9f46ecbd71b9858311ea12 + d60bc3aedeb853e2a11c0c096baaf19954dd9b752e48dea8e919e5fb29a42a8d
        System.out.println("str1_C:" + str1_C);
        byte[] localSignature = hmacSHA256(str1_C.getBytes(), appKey.getBytes());
        String localSignatureStr = Base64.encodeBase64String(localSignature);   // Signature
        System.out.println("Authorization:\n" + "OPEN-BODY-SIG AppId=" + "\"" + appId + "\"" + ", Timestamp=" + "\"" + timestamp + "\"" + ", Nonce=" + "\"" + nonce + "\"" + ", Signature=" + "\"" + localSignatureStr + "\"\n");
        return ("OPEN-BODY-SIG AppId=" + "\"" + appId + "\"" + ", Timestamp=" + "\"" + timestamp + "\"" + ", Nonce=" + "\"" + nonce + "\"" + ", Signature=" + "\"" + localSignatureStr + "\"");
    }
    /**
     * 进行加密
     *
     * @param is
     * @return 加密后的结果
     */
    private static String testSHA256(InputStream is) {
        try {
            return DigestUtils.sha256Hex(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param data
     * @param key
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public static byte[] hmacSHA256(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
        String algorithm = "HmacSHA256";
        Mac mac = Mac.getInstance(algorithm);
        mac.init(new SecretKeySpec(key, algorithm));
        return mac.doFinal(data);
    }


}
